package com.dd.cloud.user.util;

import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.documents.TextWrappingStyle;
import com.spire.doc.fields.DocPicture;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.WordUtils;
import org.apache.http.entity.ContentType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Description: Spire.Doc.Jar方式word模板转pdf文档
 * <p>
 * 导入         <id>com.e-iceblue</id>
 * <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
 * <dependency>
 * <groupId>e-iceblue</groupId>
 * <artifactId>spire.doc.free</artifactId>
 * <version>3.9.0</version>
 * </dependency>
 * @Author: czg
 * @Date: 2023/2/14 9:32
 * @Version: 1.0.0
 */
@Slf4j
public class WordToPdf {
    private static final String PATH = "temp";

    /**
     * @param dataMap:      参数map, 名需要与模板${} 一致
     * @param templateName: 模板名, word转的ftl文件
     * @return MultipartFile 返回MultipartFile文件, 用于文件上传
     * @author czg
     * @description 根据模板生成word文件 并生成pdf临时文件,转成MultipartFile文件
     * @date 2023/2/14 15:28
     */
    public static MultipartFile createWordToPdf(Map dataMap, String templateName, List<ImagePosition> positionList) {
        String filePath = null;
        MultipartFile multipartFile = null;
        //创建配置实例
        Configuration configuration = new Configuration(new Version("2.3.28"));
        //设置编码
        configuration.setDefaultEncoding("UTF-8");
        //ftl模板文件 默认在template文件夹下
        configuration.setClassForTemplateLoading(WordUtils.class, "/template");
        try {
            //临时文件夹
            String path = PATH + File.separator;
            //获取模板
            Template template = configuration.getTemplate(templateName);
            //word临时文件名
            String fname = "word" + System.currentTimeMillis() + ".doc";
            File outFile = new File(path + fname);
            filePath = path + fname;
            System.out.println(filePath);
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8));
            template.process(dataMap, out);
            out.flush();
            out.close();
            File wordFile = new File(filePath);
            //开始时间
            long old = System.currentTimeMillis();

            // Address是将要被转化的word文档
            Document document = new Document();
            //加载Word
            document.loadFromFile(filePath);
            List<File> imgFiles = null;
            if (positionList != null && !positionList.isEmpty()) {
                imgFiles = setImgToWord(document, positionList);

            }
            //pdf临时文件名
            String outPath = "pdf" + System.currentTimeMillis() + ".pdf";
            document.saveToFile(outPath, FileFormat.PDF);
            //获取文件
            File file = new File(outPath);
            FileInputStream fileInputStream = null;
            /*
              File 转 MultipartFile 为了文件上传方便
             */
            try {
                fileInputStream = new FileInputStream(file);
                multipartFile = new MockMultipartFile(file.getName(), file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //结束时间
            long now = System.currentTimeMillis();
            System.out.println("PDF转换结束 共耗时：" + ((now - old) / 1000.0) + "秒");
            wordFile.delete();
            file.delete();
            if (imgFiles != null) {
                for (File f : imgFiles) {
                    f.delete();
                }
            }
        } catch (Exception e) {
            log.error("导出word文档出错", e);
            e.printStackTrace();
            return null;
        } finally {
            return multipartFile;
        }
    }

    /**
     * @param document:     word对象
     * @param positionList: 图片的位置列表
     * @return File 图片对象
     * @description 将图片插入word文档
     * @author czg
     * @date 2023/4/3 13:43
     */
    private static List<File> setImgToWord(Document document, List<ImagePosition> positionList) {
        List<File> fileList = new ArrayList<>();
        for (ImagePosition pos : positionList) {
            // 创建 DocPicture 类的对象
            DocPicture picture = new DocPicture(document);

            File urlFile = getNetUrlHttp(pos.getSourceUrl());
            picture.loadImage(urlFile.getAbsolutePath());
            // 设置图片大小, 签字固定大小
            picture.setWidth(pos.getWidth());
            picture.setHeight(pos.getHight());
            picture.setLayoutInCell(true);
            // 将图片文本环绕方式设置为四周环绕
            picture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text);
            // 将图片插入到第几段  1：表示第一段
            document.getSections().get(0).getParagraphs().get(1).getChildObjects().insert(0, picture);
            // 设置图片的位置 水平,垂直
            picture.setHorizontalPosition(pos.getLevel());
            picture.setVerticalPosition(pos.getVertical());
            fileList.add(urlFile);
        }
        return fileList;
    }

    /**
     * @param inPath:  word临时文件路径 执行完此方法会删除
     * @param outPath: pdf临时文件路径 执行完此方法或删除
     * @return String 返回base64 pdf的字符串
     * @author czg
     * @description MultipartFile 用于文件上传
     * @date 2023/2/14 15:30
     */
    public static MultipartFile docTopdfBase64(String inPath, String outPath) {
        //本地开发环境
        String path = "temp" + File.separator;
        //上一步生成的Word文档
        outPath = path + outPath;
        File wordFile = new File(inPath);
        MultipartFile multipartFile = null;
        try {
            //开始时间
            long old = System.currentTimeMillis();
            // Address是将要被转化的word文档
            Document document = new Document();
            //加载Word
            document.loadFromFile(inPath);
            document.saveToFile(outPath, FileFormat.PDF);
            //获取文件
            File file = new File(outPath);
            FileInputStream fileInputStream = null;
            /*
              File 转 MultipartFile 为了文件上传方便
             */
            try {
                fileInputStream = new FileInputStream(file);
                multipartFile = new MockMultipartFile(file.getName(), file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //结束时间
            long now = System.currentTimeMillis();
            System.out.println("PDF转换结束 共耗时：" + ((now - old) / 1000.0) + "秒");
            wordFile.delete();
            file.delete();
        } catch (Exception e) {
            log.info("生成pdf文件流异常");
            e.printStackTrace();
            return null;
        }
        return multipartFile;
    }

    /**
     * @param sourceUrl:
     * @return File
     * @description 网络资源转本地file临时文件
     * @author czg
     * @date 2023/4/3 11:36
     */
    public static File getNetUrlHttp(String sourceUrl) {
        //对本地文件命名，path是http的完整路径，主要得到资源的名字
        String newUrl = sourceUrl;
        newUrl = newUrl.split("[?]")[0];
        String[] bb = newUrl.split("/");
        //得到最后一个分隔符后的名字
        String fileName = bb[bb.length - 1];
        //保存到本地的路径
        String filePath = PATH + File.separator + fileName;
        File file = null;
        URL urlfile;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            //判断文件的父级目录是否存在，不存在则创建
            file = new File(filePath);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            try {
                //创建文件
                file.createNewFile();
            } catch (Exception e) {
                e.printStackTrace();
            }
            //下载
            urlfile = new URL(newUrl);
            inputStream = urlfile.openStream();
            outputStream = new FileOutputStream(file);

            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != outputStream) {
                    outputStream.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    /**
     * 内部类, 图片的位置
     */
    @Data
    public static class ImagePosition {
        //水平位置
        private Integer level;
        //垂直位置
        private Integer vertical;
        //图片宽
        private Integer width = 36;
        //图片高
        private Integer hight = 47;
        //图片地址
        private String sourceUrl;

        @Override
        public String toString() {
            return "ImagePosition{" + "level=" + level + ", vertical=" + vertical + '}';
        }
    }
}
